#include "databasemanager.h"
#include "constant/DBTableConfig.h"
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
#include <stdexcept>

// 静态成员初始化
DatabaseManager* DatabaseManager::instance = nullptr;

/**
 * @brief 私有构造函数实现
 * 初始化连接状态为false，不直接打开数据库
 */
DatabaseManager::DatabaseManager() : connected(false)
{
}

/**
 * @brief 析构函数实现
 * 调用closeDatabase()确保资源释放，重置单例指针
 */
DatabaseManager::~DatabaseManager()
{
    closeDatabase();
    instance = nullptr;
}

/**
 * @brief 单例实例获取实现
 * 线程不安全版本，适合单线程应用
 * @return DatabaseManager* 唯一实例指针
 */
DatabaseManager* DatabaseManager::getInstance()
{
    if (!instance) {
        instance = new DatabaseManager();
    }
    return instance;
}

/**
 * @brief 打开数据库连接实现
 * 1. 验证输入参数合法性
 * 2. 检查SQLite驱动是否可用
 * 3. 配置并打开数据库连接
 * 4. 异常捕获与错误处理
 * @param dbName 数据库文件名
 * @return bool 连接成功状态
 */
bool DatabaseManager::openDatabase(const QString& dbName)
{
    try {
        if (dbName.isEmpty()) {
            throw std::invalid_argument("数据库名称不能为空");
        }

        // 若已连接则先关闭
        if (connected) {
            closeDatabase();
        }

        // 检查SQLite驱动是否可用
        if (!QSqlDatabase::isDriverAvailable("QSQLITE")) {
            throw std::runtime_error("SQLite驱动不可用，请检查Qt配置");
        }

        // 创建并配置数据库连接
        db = QSqlDatabase::addDatabase("QSQLITE");
        if (db.isValid()) {
            db.setDatabaseName(dbName);

            // 输出数据库文件路径便于调试
            qDebug() << "数据库文件路径:" << db.databaseName();

            // 尝试打开数据库
            if (!db.open()) {
                QString error = QString("数据库打开失败: %1").arg(db.lastError().text());
                throw std::runtime_error(error.toStdString());
            }

            qDebug() << "数据库连接成功:" << dbName;
            connected = true;
            return true;
        } else {
            throw std::runtime_error("无法创建数据库连接对象");
        }
    } catch (const std::exception& e) {
        qCritical() << "打开数据库时发生错误:" << e.what();
        connected = false;
        return false;
    } catch (...) {
        qCritical() << "打开数据库时发生未知错误";
        connected = false;
        return false;
    }
}

/**
 * @brief 关闭数据库连接实现
 * 安全关闭数据库，处理可能的异常
 */
void DatabaseManager::closeDatabase()
{
    try {
        if (connected && db.isOpen()) {
            db.close();
            connected = false;
            qDebug() << "数据库已关闭";
        }
    } catch (const std::exception& e) {
        qCritical() << "关闭数据库时发生错误:" << e.what();
    } catch (...) {
        qCritical() << "关闭数据库时发生未知错误";
    }
}

/**
 * @brief 获取数据库连接对象实现
 * 提供原始连接对象供外部高级操作使用
 * @return QSqlDatabase 数据库连接对象
 */
QSqlDatabase DatabaseManager::getDatabase() const
{
    return db;
}

/**
 * @brief 检查连接状态实现
 * 同时验证连接标志和数据库实际状态
 * @return bool 连接有效返回true
 */
bool DatabaseManager::isConnected() const
{
    return connected && db.isOpen();
}

/**
 * @brief 执行SQL语句实现（无返回结果）
 * 1. 验证连接状态和SQL合法性
 * 2. 执行SQL并处理可能的错误
 * 3. 通过异常捕获机制确保程序稳定性
 * @param sql 待执行的SQL语句
 * @param errorMsg 错误信息输出
 * @return bool 执行成功状态
 */
bool DatabaseManager::executeSql(const QString& sql, QString* errorMsg)
{
    if (errorMsg) *errorMsg = "";

    try {
        if (!isConnected()) {
            QString error = "数据库未连接";
            if (errorMsg) *errorMsg = error;
            throw std::runtime_error(error.toStdString());
        }

        if (sql.isEmpty()) {
            QString error = "SQL语句不能为空";
            if (errorMsg) *errorMsg = error;
            throw std::invalid_argument(error.toStdString());
        }

        QSqlQuery query(db);
        query.setForwardOnly(true);  // 优化查询性能

        bool success = query.exec(sql);
        if (!success) {
            QString error = QString("SQL执行失败: %1\nSQL语句: %2")
                    .arg(query.lastError().text()).arg(sql);
            if (errorMsg) *errorMsg = error;
            throw std::runtime_error(error.toStdString());
        }

        return true;
    } catch (const std::exception& e) {
        qWarning() << "SQL执行错误:" << e.what();
        return false;
    } catch (...) {
        QString error = "执行SQL时发生未知错误";
        if (errorMsg) *errorMsg = error;
        qCritical() << error;
        return false;
    }
}

/**
 * @brief 执行查询SQL实现（带返回结果）
 * 与executeSql类似，但返回查询结果集
 * @param sql 待执行的查询SQL
 * @param errorMsg 错误信息输出
 * @return QSqlQuery 查询结果对象
 */
QSqlQuery DatabaseManager::executeQuery(const QString& sql, QString* errorMsg)
{
    if (errorMsg) *errorMsg = "";

    try {
        if (!isConnected()) {
            QString error = "数据库未连接";
            if (errorMsg) *errorMsg = error;
            throw std::runtime_error(error.toStdString());
        }

        if (sql.isEmpty()) {
            QString error = "SQL语句不能为空";
            if (errorMsg) *errorMsg = error;
            throw std::invalid_argument(error.toStdString());
        }

        QSqlQuery query(db);
        query.setForwardOnly(true);  // 对于大结果集提升性能

        bool success = query.exec(sql);
        if (!success) {
            QString error = QString("查询执行失败: %1\nSQL语句: %2")
                    .arg(query.lastError().text()).arg(sql);
            if (errorMsg) *errorMsg = error;
            throw std::runtime_error(error.toStdString());
        }

        return query;
    } catch (const std::exception& e) {
        qWarning() << "查询执行错误:" << e.what();
    } catch (...) {
        QString error = "执行查询时发生未知错误";
        if (errorMsg) *errorMsg = error;
        qCritical() << error;
    }

    return QSqlQuery();  // 返回无效查询对象表示失败
}

/**
 * @brief 检查表格是否存在实现
 * 查询SQLite系统表sqlite_master判断表是否存在
 * @param tableName 表名
 * @return bool 表存在返回true
 */
bool DatabaseManager::isTableExists(const QString& tableName)
{
    if (!isConnected()) {
        qWarning() << "检查表格存在性失败：数据库未连接";
        return false;
    }

    if (tableName.isEmpty()) {
        qWarning() << "检查表格存在性失败：表名不能为空";
        return false;
    }

    QSqlQuery query(db);
    // 查询系统表判断表是否存在
    QString sql = QString("SELECT name FROM sqlite_master WHERE type='table' AND name='%1'").arg(tableName);

    if (query.exec(sql) && query.next()) {
        return true;  // 表存在
    }
    return false;   // 表不存在
}

/**
 * @brief 条件创建表实现
 * 表不存在时使用配置的SQL语句创建
 * @param tableName 表名
 * @param errorMsg 错误信息输出
 * @return bool 操作成功状态
 */
bool DatabaseManager::createTableIfNotExists(const QString& tableName, QString* errorMsg)
{
    if (errorMsg) *errorMsg = "";

    // 表已存在则直接返回成功
    if (isTableExists(tableName)) {
        return true;
    }

    // 获取预定义的建表SQL
    QString createSql = DBTableConfig::getCreateTableSql(tableName);
    if (createSql.isEmpty()) {
        QString error = QString("未找到表 %1 的创建SQL语句").arg(tableName);
        if (errorMsg) *errorMsg = error;
        qWarning() << error;
        return false;
    }

    // 执行建表SQL
    return executeSql(createSql, errorMsg);
}

/**
 * @brief 批量检查并创建所有表实现
 * 按配置的表名列表依次检查并创建表
 * @param errorMsg 累积错误信息输出
 * @return bool 所有表操作成功返回true
 */
bool DatabaseManager::checkAndCreateAllTables(QString* errorMsg)
{
    if (errorMsg) *errorMsg = "";

    if (!isConnected()) {
        QString error = "数据库未连接，无法初始化表结构";
        if (errorMsg) *errorMsg = error;
        return false;
    }

    bool allSuccess = true;
    QStringList allTables = DBTableConfig::getAllTableNames();

    // 遍历所有表名，依次检查并创建
    for (const QString& tableName : allTables) {
        QString tableError;
        if (!createTableIfNotExists(tableName, &tableError)) {
            allSuccess = false;
            qWarning() << "表" << tableName << "创建失败:" << tableError;

            // 累积错误信息
            if (errorMsg && !tableError.isEmpty()) {
                *errorMsg += QString("表 %1 创建失败: %2\n").arg(tableName, tableError);
            }
        } else {
            qDebug() << "表" << tableName << "检查/创建成功";
        }
    }

    return allSuccess;
}
